Skip to content

fix(plugins): strip empty-string args in resolver so no-arg slash commands work#47

Merged
omerakben merged 1 commit into
mainfrom
fix/resolver-strip-empty-args
May 30, 2026
Merged

fix(plugins): strip empty-string args in resolver so no-arg slash commands work#47
omerakben merged 1 commit into
mainfrom
fix/resolver-strip-empty-args

Conversation

@omerakben
Copy link
Copy Markdown
Owner

Why

Found by dogfooding the freshly-published plugin: /code-oz-doctor (and /code-oz-init) fail on every no-arg invocation.

Each command card renders <subcommand> "$ARGUMENTS". With no user args, Claude Code substitutes an empty $ARGUMENTS, so the shell line becomes ... resolve-code-oz.sh doctor "". The engine's 0.21.1 subcommand dispatcher (which split doctor into providers|tools|git|run) treats "" as a subcommand name and exits 1 (unknown subcommand ''). The engine handles zero positionals fine — the empty string is the problem.

Invocation Before
doctor exit 0 ✓
doctor "" unknown subcommand '' → exit 1 ✗

doctor/init break every time; run/resume carry a latent trailing empty.

What

Fix at the layer that introduces the artifact — the resolver strips empty-string positionals before both the PATH-exec and npx branches. An empty positional is never meaningful to code-oz, so doctor "" becomes doctor.

  • Array form preserves args containing spaces; ${a[@]+"${a[@]}"} keeps the empty-array expansion safe under set -u on bash 3.2 (macOS default).
  • RED-first: two empty-strip tests (PATH + npx branches) + a spaces-preservation guard.

Verification

  • On bash 3.2.57: resolve-code-oz.sh doctor "" now exits 0; init "" is byte-identical to init (its exit 1 is the legit ".code-oz/ already exists" guard).
  • 3815 offline tests pass; typecheck clean.

Follow-up (not in this PR)

A carefully-scoped engine-level normalization — treat an empty subcommand token as absent, not a blanket argv filter (which would eat legitimate empty flag values like run --message "") — would harden direct-CLI and other non-plugin callers. Tracked as a recommended follow-up.

…mands work

Every plugin command card renders `<subcommand> "$ARGUMENTS"`. When the user
runs a command with no arguments, Claude Code substitutes an empty $ARGUMENTS,
leaving a literal empty positional:

  bash resolve-code-oz.sh doctor ""

The engine's 0.21.1 subcommand dispatcher (doctor split into
providers|tools|git|run) treats "" as a subcommand name, matches nothing, and
exits 1 ("unknown subcommand ''"). doctor and init break on every no-arg
invocation; run and resume carry a latent trailing empty. The engine already
does the right thing with zero positionals — the empty string is what breaks
it.

Fix at the layer that introduces the artifact: the resolver drops empty-string
positionals before both the PATH-exec and npx branches. An empty positional is
never meaningful to code-oz, so `doctor ""` becomes `doctor`. Array form
preserves args containing spaces; ${a[@]+"${a[@]}"} keeps the empty-array
expansion safe under `set -u` on bash 3.2 (macOS default). RED-first: two
empty-strip tests (PATH + npx branches) plus a spaces-preservation guard.

Verified on bash 3.2.57: `resolve-code-oz.sh doctor ""` now exits 0; `init ""`
is byte-identical to `init`. 3815 offline tests pass; typecheck clean.

A separate, carefully-scoped engine-level normalization (treat an empty
subcommand token as absent, without a blanket argv filter that would eat empty
flag values) remains a recommended follow-up to harden non-plugin callers.
Copilot AI review requested due to automatic review settings May 30, 2026 15:38
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 30, 2026

Warning

Review limit reached

@omerakben, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 17 minutes and 45 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4a94e67b-c70a-495a-b86b-e3ecda514c91

📥 Commits

Reviewing files that changed from the base of the PR and between 8d2c290 and 9a419dc.

📒 Files selected for processing (2)
  • plugins/code-oz/scripts/resolve-code-oz.sh
  • tests/plugins/bootstrap-resolver.test.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/resolver-strip-empty-args

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates resolve-code-oz.sh to filter out empty-string positional arguments before executing code-oz or invoking npx, preventing errors with empty arguments. Corresponding tests have been added to verify this behavior. Feedback suggests replacing a cryptic bash array expansion with a more readable conditional check to improve maintainability and robustness.

for arg in "$@"; do
[ -n "${arg}" ] && filtered_args+=("${arg}")
done
set -- ${filtered_args[@]+"${filtered_args[@]}"}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The expression ${filtered_args[@]+"${filtered_args[@]}"} is highly cryptic and relies on subtle bash expansion and quoting rules that can be difficult to maintain or easily broken by future changes (e.g., if someone tries to wrap the outer expression in double quotes, which would introduce an empty string argument when the array is empty).

A much more readable, standard, and robust approach that is fully compatible with set -u and older bash versions (like bash 3.2 on macOS) is to check the array length explicitly using ${#filtered_args[@]}.

Suggested change
set -- ${filtered_args[@]+"${filtered_args[@]}"}
if [ ${#filtered_args[@]} -gt 0 ]; then
set -- "${filtered_args[@]}"
else
set --
fi

@omerakben omerakben merged commit 9679c63 into main May 30, 2026
3 of 4 checks passed
@omerakben omerakben deleted the fix/resolver-strip-empty-args branch May 30, 2026 15:39
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes the plugin resolver so Claude Code slash command cards that pass an empty "$ARGUMENTS" no longer forward a literal empty string to the code-oz engine.

Changes:

  • Adds empty-string argument filtering in resolve-code-oz.sh before PATH and npx resolution.
  • Adds regression tests covering PATH execution, npx fallback, and preservation of arguments containing spaces.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
plugins/code-oz/scripts/resolve-code-oz.sh Filters empty positional arguments before invoking the engine.
tests/plugins/bootstrap-resolver.test.ts Adds resolver tests for empty argument stripping and space-containing argument preservation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants